package com.example.blogserver.service.Impl;

import com.example.blogserver.service.RegService;
import com.example.blogserver.a_utils.GetBean;
import com.example.blogserver.a_utils.ResponseBodyMessage;
import com.example.blogserver.mapper.UserMapper;
import com.example.blogserver.pojo.User;
import com.example.blogserver.a_utils.BuildUserId;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;

@SuppressWarnings({"all"})
@Service
public class RegServiceImpl implements RegService {
    //获取生成的验证码，将单个邮箱对应的验证码和邮箱账号存储起来
    public static String EmailCode = new String();

    //获取Redis操作对象
    private static RedisTemplate redisTemplate = (RedisTemplate) GetBean.getBean("redisTemplate");

    @Autowired
    private com.example.blogserver.a_utils.EmailCode code;

    @Autowired
    private BuildUserId account;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Value("${EmailToken}")
    private String emailToken;

    /**
     * 发送邮箱验证码逻辑处理
     */
    @Override
    public ResponseBodyMessage<Boolean> sendEmailCode(HttpServletRequest request, String emailId) {
        ResponseBodyMessage responseBodyMessage = new ResponseBodyMessage();
        //判断是否发送过验证码
        HttpSession session = request.getSession(true);//允许创建
        if (session != null && session.getAttribute("emailId") != null){
            //说明发送过验证码
            String key = (String) session.getAttribute("emailId");
            //判断验证码是否过期
            Boolean ret = redisTemplate.hasKey(key);
            if (ret){
                //表示key未过期，不可以重新发送验证码
                return new ResponseBodyMessage<>(-1,"已经发送过验证码，短时间内不可以重复发送",false);
            }
            //走到这，就表示验证码过期了，继续往下走发送验证码
            //移除旧的session当中存储的信息
            session.removeAttribute("emailId");
        }
        //进行验证码发送服务
        boolean ret = sendCode(request, emailId);
        if (ret){
            //验证码发送成功，将邮箱存储在session当中，将验证码存储在Redis当中，设置120秒过期
            session.setAttribute("emailId",emailId);
            //将验证码存储在Redis当中
            String checkCode = RegServiceImpl.EmailCode;
            redisTemplate.opsForValue().set(emailId,checkCode,120, TimeUnit.SECONDS);
            //封装响应数据
            responseBodyMessage.setStatus(1);
            responseBodyMessage.setMessage("验证码发送成功，验证码将于120秒之后过期，请尽快完成注册~");
            responseBodyMessage.setData(true);
        }else {
            responseBodyMessage.setStatus(-1);
            responseBodyMessage.setMessage("邮箱信息有误，请检查邮箱的正确性~");
            responseBodyMessage.setData(false);
        }
        return responseBodyMessage;

    }

    /**
     * 发送验证码核心代码
     */
    private boolean sendCode(HttpServletRequest request, String emailId){
        SimpleEmail email = new SimpleEmail();
        //qq：qq邮件服务器的端口号
        email.setSslSmtpPort("465");
        email.setHostName("smtp.qq.com");
        email.setAuthentication("3300291815@qq.com", emailToken);
        email.setCharset("UTF-8");
        try {
            email.addTo(emailId);
            email.setFrom("3300291815@qq.com");
            email.setSubject("【知识海洋】");
            //生成六位数随机验证码
            EmailCode = buildEmailCode();
            //封装验证码信息
            email.setMsg("尊敬的用户，您好，您的邮箱验证码为：" + EmailCode  + ",您当前正在执行邮箱绑定服务，如非本人操作，请忽略此邮件~");
            email.send();
            return true;
        }catch (EmailException e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 生成随机六位数验证码
     */
    public String buildEmailCode(){
        code.init();//生成随机六位验证码
        return code.getEmailCode();
    }

    @Override
    public ResponseBodyMessage<User> Reg(HttpServletRequest request, String emailId, String emailCode, String passworda, String passwordb) {
        //调用服务层代码处理
        int ret = checkMse(request,emailId,emailCode,passworda,passwordb);
        ResponseBodyMessage responseBodyMessage = new ResponseBodyMessage();
        if (ret == 1){
            //信息无误，进行注册
            //1.判断邮箱是否使用过
            boolean res = checkEmail(emailId);
            if (res){
                //表示邮箱被使用过
                responseBodyMessage.setStatus(-1);
                responseBodyMessage.setMessage("该邮箱已经被注册过了，请换个邮箱再来注册~");
                responseBodyMessage.setData(null);
            }else {
                //邮箱未被使用
                responseBodyMessage.setStatus(1);
                String userId = buildUser(emailId,passworda);
                User user = new User();
                user.setUserid(userId);
                user.setEmail(emailId);
                user.setPassword(passworda);
                responseBodyMessage.setMessage("注册成功，您的账号为：" + userId + ",后续您可通过账号进行登录~");
                responseBodyMessage.setData(user);
            }
        }else{
            responseBodyMessage.setStatus(-1);
            responseBodyMessage.setData(null);
            if (ret == 2){
                responseBodyMessage.setMessage("您当前还未发送验证码，请先完成发送验证码~");
            }else if (ret == 3){
                responseBodyMessage.setMessage("邮箱信息有误，请检查后重新发送~");
            }else if (ret == 4){
                responseBodyMessage.setMessage("验证码过期，请重新发送~");
            }else if (ret == 5){
                responseBodyMessage.setMessage("确认密码和初始密码不一致，请重新输入~");
            }else if (ret == 6){
                responseBodyMessage.setMessage("验证码错误，请检查后重新输入~");
            }
        }
        return responseBodyMessage;
    }

    /**
     * 对注册信息进行校验
     */
    public int checkMse(HttpServletRequest request,
                        String emailId,
                        String emailCode,
                        String passworda,
                        String passwordb) {
        //获取session当中存储的id
        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute("emailId") == null){
            //未发送验证码
            return 2;
        }
        //session会话当中存储着邮箱信息
        String email = (String) session.getAttribute("emailId");
        if (!email.equals(emailId)){
            //表示未使用同一个邮箱
            return 3;
        }
        //判断是否过期
        boolean res = redisTemplate.hasKey(email);
        if (!res){
            //验证码过期
            return 4;
        }
        //判断密码的一致性
        if (!passworda.equals(passwordb)){
            //密码不一致
            return 5;
        }
        //获取redis当中存储的code，判断code一致性
        String checkCode = (String) redisTemplate.opsForValue().get(email);
        if (!checkCode.equals(emailCode)){
            return 6;
        }
        //删除Redis当中存储的code
        redisTemplate.delete(email);
        //校验通过
        return 1;
    }

    /**
     * 检查邮箱是否被使用过
     */
    public boolean checkEmail(String emailId) {
        User user = userMapper.checkEmail(emailId);
        if (user == null){
            //未被使用
            return false;
        }else {
            //已经被使用
            return true;
        }
    }

    /**
     * 生成10位数随机账号
     */
    public String buildId(){
        account.init();
        return account.getPersonId();
    }

    /**
     * 创建新用户
     */
    public String buildUser(String emailId, String passworda) {
        //生成10位数账号
        String userId = buildId();
        //生成的账号在数据库中查询，如果存在就重新生成
        //如果不存在，则说明该账号可以使用，于是就将该账号、邮箱、存储到新的用户信息当中
        User user = userMapper.queryUser(userId);
        while (user != null){
            //表示账号使用过，重新生成
            userId = buildId();
            user = userMapper.queryUser(userId);
        }
        //当结果集为空时，则代表该随机10位数账号可用
        //对密码进行加密
        String BC = bCryptPasswordEncoder.encode(passworda);
        userMapper.createUser(userId,BC,emailId);
        return userId;
    }
}
